package com.netkit;

import com.netkit.event.HeatbeatListener;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class NetkitServer
{
  private final NetkitContext context;
  private String bindHost = "0.0.0.0";
  private int port = 8000;
  private int maxConnections = 100000;
  private ServerBootstrap bootstrap = null;
  private ChannelFactory channelFactory = null;
  private Channel listenerChannel = null;
  private int maxMessagePacketSize = 1048576;
  private ScheduledExecutorService heatbeatService = Executors.newScheduledThreadPool(1);

  public int getMaxMessagePacketSize() {
    return this.maxMessagePacketSize;
  }

  public void setMaxMessagePacketSize(int maxPacketLength) {
    this.maxMessagePacketSize = maxPacketLength;
  }

  public NetkitServer(NetkitContext context) {
    this.context = context;
  }

  public NetkitServer(NetkitContext context, int port) {
    this.context = context;
    this.port = port;
  }

  public NetkitServer(NetkitContext context, String bindHost, int port) {
    this.context = context;
    this.port = port;
    this.bindHost = bindHost;
  }

  public void setMaxConnections(int maxConnections) {
    this.maxConnections = maxConnections;
  }

  public synchronized void startup() {
    ExecutorService bossExecutor = this.context.getBossExecutor();
    ExecutorService workerExecutor = this.context.getWorkerExecutor();

    this.channelFactory = new NioServerSocketChannelFactory(bossExecutor, workerExecutor);

    this.bootstrap = new ServerBootstrap(this.channelFactory);
    this.context.setMaxConnections(this.maxConnections);

    NetkitChannelPipelineFactory pipelineFactory = new NetkitChannelPipelineFactory(this.context);

    this.bootstrap.setPipelineFactory(pipelineFactory);
    this.bootstrap.setOption("child.tcpNoDelay", Boolean.valueOf(true));
    this.bootstrap.setOption("child.keepAlive", Boolean.valueOf(true));

    this.listenerChannel = this.bootstrap.bind(new InetSocketAddress(this.bindHost, this.port));

    this.heatbeatService.scheduleAtFixedRate(new HeatbeatListener(this.context), 30L, 30L, TimeUnit.SECONDS);
  }

  public void shutdown()
  {
    this.listenerChannel.close();

    this.context.release();

    this.channelFactory.releaseExternalResources();

    this.heatbeatService.shutdown();

    this.bootstrap.releaseExternalResources();
  }

  public NetkitContext getServerContext() {
    return this.context;
  }
}